#include "stdint.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

#include "LPC802.h"
#include "drv_ws2812.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define WS_TRANSFER_SIZE   (WS2812_PIXELS*24)   // Transfer dataSize

#define WS_BIT              24
#define WS_BIT1             0x7C
#define WS_BIT0             0x60

uint32_t    ws2812_color_tbl[8]=
{
    0xFF8080,
    WS2812_WHITE,
    WS2812_RED,
    WS2812_GREEN,
    WS2812_BLUE,
    WS2812_YELLOW,
    WS2812_CYAN,
    WS2812_PURPLE,
};
/*******************************************************************************
 * Variables
 ******************************************************************************/
volatile uint8_t g_WS2812TxBuf[WS_TRANSFER_SIZE];   // WS2812 Strip transmit data buffer

/*
 * @brief   WS2812_StripInit
 * @param   NULL
 * @return  NULL
 */
void WS2812_Init(void)
{
    WS2812_ClearData();
    WS2812_SendData();
}


/*
 * @brief   WS2812_PixelSetBuff
 * @param   n, LED num / c, color / brightness, brightness
 * @return  NULL
 */
void WS2812_PixelSetIndexColor(uint16_t n, uint32_t color)
{
    volatile WS2812_ARGB_U l_color;
    uint16_t c_temp;
    
    if(n < WS2812_PIXELS)
    {
        memset((void *)&g_WS2812TxBuf[n*WS_BIT], WS_BIT0, 24);
        l_color.u32_rgba = color;
        c_temp = l_color.s_argb.a + 1;
        l_color.s_argb.r = (l_color.s_argb.r * c_temp) >> 8;
        l_color.s_argb.g = (l_color.s_argb.g * c_temp) >> 8;
        l_color.s_argb.b = (l_color.s_argb.b * c_temp) >> 8;
        
        if( ((l_color.s_argb.g>>7)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+0] = WS_BIT1;
        if( ((l_color.s_argb.g>>6)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+1] = WS_BIT1;
        if( ((l_color.s_argb.g>>5)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+2] = WS_BIT1;
        if( ((l_color.s_argb.g>>4)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+3] = WS_BIT1;
        if( ((l_color.s_argb.g>>3)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+4] = WS_BIT1;
        if( ((l_color.s_argb.g>>2)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+5] = WS_BIT1;
        if( ((l_color.s_argb.g>>1)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+6] = WS_BIT1;
        if( ((l_color.s_argb.g>>0)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+7] = WS_BIT1;
        
        if( ((l_color.s_argb.r>>7)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+0] = WS_BIT1;
        if( ((l_color.s_argb.r>>6)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+1] = WS_BIT1;
        if( ((l_color.s_argb.r>>5)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+2] = WS_BIT1;
        if( ((l_color.s_argb.r>>4)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+3] = WS_BIT1;
        if( ((l_color.s_argb.r>>3)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+4] = WS_BIT1;
        if( ((l_color.s_argb.r>>2)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+5] = WS_BIT1;
        if( ((l_color.s_argb.r>>1)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+6] = WS_BIT1;
        if( ((l_color.s_argb.r>>0)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+7] = WS_BIT1;
        
        if( ((l_color.s_argb.b>>7)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+0] = WS_BIT1;
        if( ((l_color.s_argb.b>>6)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+1] = WS_BIT1;
        if( ((l_color.s_argb.b>>5)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+2] = WS_BIT1;
        if( ((l_color.s_argb.b>>4)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+3] = WS_BIT1;
        if( ((l_color.s_argb.b>>3)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+4] = WS_BIT1;
        if( ((l_color.s_argb.b>>2)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+5] = WS_BIT1;
        if( ((l_color.s_argb.b>>1)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+6] = WS_BIT1;
        if( ((l_color.s_argb.b>>0)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+7] = WS_BIT1;
    }
}

void WS2812_PixelSetIndexRGB(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
{    
    if(n < WS2812_PIXELS)
    {
        memset((void *)&g_WS2812TxBuf[n*WS_BIT], WS_BIT0, 24);

        if( ((g>>7)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+0] = WS_BIT1;
        if( ((g>>6)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+1] = WS_BIT1;
        if( ((g>>5)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+2] = WS_BIT1;
        if( ((g>>4)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+3] = WS_BIT1;
        if( ((g>>3)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+4] = WS_BIT1;
        if( ((g>>2)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+5] = WS_BIT1;
        if( ((g>>1)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+6] = WS_BIT1;
        if( ((g>>0)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 0+7] = WS_BIT1;
        
        if( ((r>>7)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+0] = WS_BIT1;
        if( ((r>>6)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+1] = WS_BIT1;
        if( ((r>>5)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+2] = WS_BIT1;
        if( ((r>>4)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+3] = WS_BIT1;
        if( ((r>>3)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+4] = WS_BIT1;
        if( ((r>>2)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+5] = WS_BIT1;
        if( ((r>>1)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+6] = WS_BIT1;
        if( ((r>>0)&0x01))  g_WS2812TxBuf[n*WS_BIT+ 8+7] = WS_BIT1;
        
        if( ((b>>7)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+0] = WS_BIT1;
        if( ((b>>6)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+1] = WS_BIT1;
        if( ((b>>5)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+2] = WS_BIT1;
        if( ((b>>4)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+3] = WS_BIT1;
        if( ((b>>3)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+4] = WS_BIT1;
        if( ((b>>2)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+5] = WS_BIT1;
        if( ((b>>1)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+6] = WS_BIT1;
        if( ((b>>0)&0x01))  g_WS2812TxBuf[n*WS_BIT+16+7] = WS_BIT1;
    }
}
/*
 * @brief   strip_clear, clean-up LED strip display
 * @param   NULL
 * @return  NULL
 */
void WS2812_ClearData(void)
{
    memset((void *)&g_WS2812TxBuf[0], WS_BIT0, (WS_TRANSFER_SIZE));//
}

/*
 * @brief   color_dim dimme color
 * @param   color, number of LEDs
 * @return  dimmed color
 */
void WS2812_SendData(void)
{
    uint32_t    i;
    for(i=0;i<WS_TRANSFER_SIZE;i++)
    {
        while ((SPI0->STAT & 0x02) == 0);
        SPI0->TXDATCTL = g_WS2812TxBuf[i] | 0x07730000;
    }
}

void WS2812_ShowRGB(uint8_t r,uint8_t g,uint8_t b)
{
    uint8_t i;

    for(i=0; i<WS2812_PIXELS; i++)
    {
        WS2812_PixelSetIndexRGB(i, r,g,b);
    }
    WS2812_SendData();
}

void WS2812_ShowColor(uint32_t color)
{
    uint8_t i;

    for(i=0; i<WS2812_PIXELS; i++)
    {
        WS2812_PixelSetIndexColor(i, color);
    }
    WS2812_SendData();
}

void WS2812_ShowBuff(uint8_t *buff)
{
    uint8_t i;
    uint8_t *pLedData = buff;

    for(i=0; i<WS2812_PIXELS; i++)
    {
        WS2812_PixelSetIndexRGB(i, pLedData[0],pLedData[1],pLedData[2]);
        pLedData += 3;
    }
    WS2812_SendData();
}



